package com.yh.csx.bsf.flow.engine.api;

import com.sun.deploy.net.HttpUtils;
import com.unboundid.ldap.sdk.unboundidds.logs.UnbindRequestAccessLogMessage;
import com.yh.csx.bsf.core.http.DefaultHttpClient;
import com.yh.csx.bsf.core.util.JsonUtils;
import com.yh.csx.bsf.core.util.LogUtils;
import com.yh.csx.bsf.core.util.StringUtils;
import com.yh.csx.bsf.flow.core.base.Variable;
import com.yh.csx.bsf.flow.core.db.ConvertUtil;
import com.yh.csx.bsf.flow.engine.state.StateEngineException;
import com.yh.csx.bsf.flow.provider.enums.SystemVariable;
import lombok.val;
import lombok.var;

import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class Api {
    public static String run(Integer flowId,Integer taskId,String code, Map<String, Variable> flowVariables){
        try {
            code = filterNote(code);
            initSystemVariable(flowId,taskId,flowVariables);
            code = variableReplace(code,flowVariables);
            val rex = java.util.regex.Pattern.compile("【api\\.(.*?)\\((.*?)\\)】").matcher(code);
            while (rex.find()) {
                val text = rex.group(0);
                val method = rex.group(1);
                val params = removeParamChar(rex.group(2)).split(",");
                var result = "";
                String callMessage="流程id: "+flowId;
                boolean hasApi=false;
                try {
                    callMessage+=" 方法: "+ StringUtils.nullToEmpty(method) +" 参数: "+ StringUtils.nullToEmpty(JsonUtils.serialize(params));
                    if ("httpGet".equalsIgnoreCase(method)) {
                        result = httpGet(flowId,params[0]);
                        hasApi=true;
                    } else if ("user.getByDepartment".equalsIgnoreCase(method)) {
                        result = String.join(",", UserApi.getByDepartment(flowId,params[0], params[1]));
                        hasApi=true;
                    } else if ("user.getByParentDepartment".equalsIgnoreCase(method)) {
                        result = String.join(",", UserApi.getByParentDepartment(flowId,params[0], params[1], ConvertUtil.strToInt(params[2])));
                        hasApi=true;
                    }
                    callMessage+=" 结果: "+StringUtils.nullToEmpty(result);
                    if(hasApi) {
                        code = code.replace(text, result);
                        LogUtils.info(Api.class, "flow", callMessage);
                    }
                }catch (Exception e){
                    LogUtils.error(Api.class,"flow",callMessage,e);
                    throw e;
                }

            }
            return code;
        }
        catch (Exception exp){
            throw new StateEngineException(flowId,"方法解析出错",exp);
        }
    }

    public static String num(Integer flowId, String code, List<String> results)
    {
        try {
            val rex = java.util.regex.Pattern.compile("【api.num(.*?)】").matcher(code);
            while (rex.find()) {
                val text = rex.group(0);
                val result = removeParamChar(rex.group(1));
                var num=0L;
                if("".equals(result)){
                    num=results.size();
                }
                else {
                    num = results.stream().filter(c -> c.equals(result)).count();
                }
                code = code.replace(text,num+"");
            }
            return code;
        }
        catch (Exception exp){
            throw new StateEngineException(flowId,"api.num 解析出错",exp);
        }
    }
    public static void initSystemVariable(Integer flowId,Integer taskId,Map<String, Variable> flowVariables){
        flowVariables.put(SystemVariable.SYSTEM_FLOW_ID,new Variable(SystemVariable.SYSTEM_FLOW_ID,(flowId==null?0:flowId)+"",""));
        flowVariables.put(SystemVariable.SYSTEM_TASK_ID,new Variable(SystemVariable.SYSTEM_TASK_ID,(taskId==null?0:taskId)+"",""));
    }
    public static String variableReplace(String code, Map<String, Variable> flowVariables){
        var variables =  CommonApi.filterSystemChar(flowVariables.values());
        val rex = java.util.regex.Pattern.compile("【@(.*?)】").matcher(code);
        while (rex.find()) {
            val variableText = rex.group(0);
            val variable = variables.get(rex.group(1));
            if(variable!=null) {
                code = code.replace(variableText,variable.getValue());
            }
        }
        return code;
    }

    public static String httpGet(int flowid,String code)
    {
        try {
            code = urlEncode(flowid,code);
            code = DefaultHttpClient.Default.get(code);
            return code;
        }
        catch (Exception exp){
            throw new StateEngineException(flowid,"httpGet解析出错:"+ StringUtils.nullToEmpty(code),exp);
        }
    }

    public static String urlEncode(Integer flowId,String code){
        try {
            val rex = java.util.regex.Pattern.compile("〖(.*?)〗").matcher(code);
            while (rex.find()) {
                val text = rex.group(0);
                var result = removeParamChar(rex.group(1));
                result = URLEncoder.encode(result,"utf-8");
                code = code.replace(text,result);
            }
            return code;
        }
        catch (Exception exp){
            throw new StateEngineException(flowId," httpGet下urlencode 解析出错",exp);
        }
    }

    private static String removeParamChar(String code){
        if(code!=null) {
            code = org.springframework.util.StringUtils.trimLeadingCharacter(code, '(');
            code = org.springframework.util.StringUtils.trimTrailingCharacter(code, ')');
            code = org.springframework.util.StringUtils.trimLeadingCharacter(code, '\"');
            code = org.springframework.util.StringUtils.trimTrailingCharacter(code, '\"');
            code = org.springframework.util.StringUtils.trimLeadingCharacter(code, '\'');
            code = org.springframework.util.StringUtils.trimTrailingCharacter(code, '\'');
        }
        return code;
    }

    /**
     * 过滤注释
     * @param code
     * @return
     */
    public static String filterNote(String code){
        code = StringUtils.nullToEmpty(code);
        StringBuilder sb = new StringBuilder();
        var codes = code.split("\n");
        for (var c : codes) {
            if (!c.startsWith("//")) {
                sb.append(c + "\n");
            }
        }
        return org.springframework.util.StringUtils.trimTrailingCharacter(sb.toString(),'\n');
    }

}
